﻿using System;
using System.Windows;
using System.Windows.Threading;

namespace LogoUI.ViewModels
{
    internal static class Dispatch
    {
#if !SILVERLIGHT
        private static Action<Action, bool, DispatcherPriority> s_dispatch;
#else
        private static Action<Action, bool> s_dispatch;

#endif
        public static void BeginOnUiThread(Action action)
        {
            BeginOnUiThread(
#if !SILVERLIGHT
DispatcherPriority.DataBind,
#endif
 action);
        }
#if !SILVERLIGHT
        public static void BeginOnUiThread(DispatcherPriority prio, Action action)
        {
            if (s_dispatch == null)
            {
                InitializeDispatch();
            }

            s_dispatch(action, true, prio);
        }
#endif
        public static void OnUiThread(Action action)
        {
            OnUiThread(
#if !SILVERLIGHT
DispatcherPriority.DataBind,
#endif
 action);
        }
#if !SILVERLIGHT
        /// <summary>
        /// Executes the action on the UI thread.
        /// </summary>
        /// <param name="priority">priority</param>
        /// <param name="action">The action to execute.</param>
        public static void OnUiThread(DispatcherPriority priority, Action action)
        {
            if (s_dispatch == null)
            {
                InitializeDispatch();
            }

            s_dispatch(action, false, priority);
        }
#endif
        /// <summary>
        /// Initializes the framework using the current dispatcher.
        /// </summary>
        public static void InitializeDispatch()
        {
            Dispatcher dispatcher = null;
#if SILVERLIGHT
            dispatcher = Deployment.Current.Dispatcher;
#else
            if (Application.Current != null && Application.Current.Dispatcher != null)
                dispatcher = Application.Current.Dispatcher;
#endif
            if (dispatcher == null)
                throw new InvalidOperationException("Dispatch is not initialized correctly");

            s_dispatch = (action, async
#if !SILVERLIGHT
, prio
#endif
) =>
            {
                if (dispatcher.CheckAccess())
                {
                    action();
                }
                else if (!async)
                {
#if !SILVERLIGHT
                    dispatcher.Invoke(prio, action);
#else
                var waitHandle = new ManualResetEvent(false);
                Exception exception = null;
                dispatcher.BeginInvoke(() =>
                {
                    try
                    {
                        action();
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }
                    waitHandle.Set();
                });
                waitHandle.WaitOne();
                if (exception != null)
                    throw new TargetInvocationException("An error occurred while dispatching a call to the UI Thread", exception);
                
#endif
                }
                else
                {
                    //Vlad, i had to lower the priority because Maikey asked to add a fading effect on the map
                    //and when priority is DataBind, animation was not showing
                    dispatcher.BeginInvoke(action
#if !SILVERLIGHT
, prio
#endif
);
                }
            };
        }

    }
}
